Ext.form.MultiComboBox = Ext.extend(Ext.form.TriggerField, {  
    defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},  
    listClass: '',  
    selectedClass: 'x-combo-selected',  
    triggerClass : 'x-form-arrow-trigger',  
    shadow:'sides',  
    listAlign: 'tl-bl?',  
    maxHeight: 300,  
    triggerAction: 'query',  
    minChars : 4,  
    typeAhead: false,  
    queryDelay: 500,  
    pageSize: 0,  
    selectOnFocus:false,  
    queryParam: 'query',  
    loadingText: 'Loading...',  
    resizable: false,  
    handleHeight : 8,  
    editable: true,  
    allQuery: '',  
    mode: 'remote',  
    minListWidth : 70,  
    forceSelection:false,  
    typeAheadDelay : 250,  
    displaySeparator:';',  
    valueSeparator:',',  
    lazyInit : true,  
  
    initComponent : function(){  
        Ext.form.ComboBox.superclass.initComponent.call(this);  
        this.addEvents(  
            'expand',  
            'collapse',  
            'beforeselect',  
            'select',  
            'beforequery'  
        );  
        if(this.transform){  
            this.allowDomMove = false;  
            var s = Ext.getDom(this.transform);  
            if(!this.hiddenName){  
                this.hiddenName = s.name;  
            }  
            if(!this.store){  
                this.mode = 'local';  
                var d = [], opts = s.options;  
                for(var i = 0, len = opts.length;i < len; i++){  
                    var o = opts[i];  
                    var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;  
                    if(o.selected) {  
                        this.value = value;  
                    }  
                    d.push([value, o.text]);  
                }  
                this.store = new Ext.data.SimpleStore({  
                    'id': 0,  
                    fields: ['value', 'text'],  
                    data : d  
                });  
                this.valueField = 'value';  
                this.displayField = 'text';  
            }  
            s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference  
            if(!this.lazyRender){  
                this.target = true;  
                this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);  
                Ext.removeNode(s); // remove it  
                this.render(this.el.parentNode);  
            }else{  
                Ext.removeNode(s); // remove it  
            }  
  
        }  
        this.selectedIndex = -1;  
        if(this.mode == 'local'){  
            if(this.initialConfig.queryDelay === undefined){  
                this.queryDelay = 10;  
            }  
            if(this.initialConfig.minChars === undefined){  
                this.minChars = 0;  
            }  
        }  
    },  
  
    // private  
    onRender : function(ct, position){  
        Ext.form.ComboBox.superclass.onRender.call(this, ct, position);  
        var disValue="";  
        if(this.hiddenName){  
            this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},  
                    'before', true);  
          var hvalue=this.hiddenValue !== undefined ? this.hiddenValue :  
                this.value !== undefined ? this.value : '';  
          var hvalueArray=hvalue.split(this.valueSeparator);  
            
          for(var i=0;i<this.store.data.length;i++){  
                 var r = this.store.getAt(i);     
                 var newValue = r.data[this.displayField];  
                  var v=r.data[this.valueField];  
                  for(var j=0;j<hvalueArray.length;j++){  
                    if(hvalueArray[j]==v){  
                        disValue+=newValue+this.displaySeparator;  
                    }  
                  }  
                   
          }       
            this.hiddenField.value =this.hiddenValue !== undefined ? this.hiddenValue :  
                this.value !== undefined ? this.value : '';  
            this.el.dom.removeAttribute('name');  
        }  
        if(Ext.isGecko){  
            this.el.dom.setAttribute('autocomplete', 'off');  
        }  
  
        if(!this.lazyInit){  
            this.initList();  
        }else{  
            this.on('focus', this.initList, this, {single: true});  
        }  
  
        if(!this.editable){  
            this.editable = true;  
            this.setEditable(false);  
        }  
        this.setValue(disValue);  
    },  
  
    initList : function(){  
        if(!this.list){  
            var cls = 'x-combo-list';  
  
            this.list = new Ext.Layer({  
                shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false  
            });  
  
            var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);  
            this.list.setWidth(lw);  
            this.list.swallowEvent('mousewheel');  
            this.assetHeight = 0;  
  
            if(this.title){  
                this.header = this.list.createChild({cls:cls+'-hd', html: this.title});  
                this.assetHeight += this.header.getHeight();  
            }  
  
            this.innerList = this.list.createChild({cls:cls+'-inner'});  
            this.innerList.on('mouseover', this.onViewOver, this);  
            this.innerList.on('mousemove', this.onViewMove, this);  
            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'))  
  
            if(this.pageSize){  
                this.footer = this.list.createChild({cls:cls+'-ft'});  
                this.pageTb = new Ext.PagingToolbar({  
                    store:this.store,  
                    pageSize: this.pageSize,  
                    renderTo:this.footer  
                });  
                this.assetHeight += this.footer.getHeight();  
            }  
  
            if(!this.tpl){  
                //alert(cls);  
                //x-combo-list-item  
                this.tpl = '<tpl for="."><div class="'+cls+'-item"><span class="unchecked" id="checkBox_{' + this.displayField + '}"+ width="20">&nbsp;&nbsp;&nbsp;&nbsp;</span>{' + this.displayField + '}</div></tpl>';  
            }  
            this.view = new Ext.DataView({  
                applyTo: this.innerList,  
                tpl: this.tpl,  
                singleSelect: true,  
                selectedClass: this.selectedClass,  
                itemSelector: this.itemSelector || '.' + cls + '-item'  
            });  
  
            this.view.on('click', this.onViewClick, this);  
  
            this.bindStore(this.store, true);  
  
            if(this.resizable){  
                this.resizer = new Ext.Resizable(this.list,  {  
                   pinned:true, handles:'se'  
                });  
                this.resizer.on('resize', function(r, w, h){  
                    this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;  
                    this.listWidth = w;  
                    this.innerList.setWidth(w - this.list.getFrameWidth('lr'));  
                    this.restrictHeight();  
                }, this);  
                this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');  
            }  
        }  
    },  
  
    bindStore : function(store, initial){  
        if(this.store && !initial){  
            this.store.un('beforeload', this.onBeforeLoad, this);  
            this.store.un('load', this.onLoad, this);  
            this.store.un('loadexception', this.collapse, this);  
            if(!store){  
                this.store = null;  
                if(this.view){  
                    this.view.setStore(null);  
                }  
            }  
        }  
        if(store){  
            this.store = Ext.StoreMgr.lookup(store);  
  
            this.store.on('beforeload', this.onBeforeLoad, this);  
            this.store.on('load', this.onLoad, this);  
            this.store.on('loadexception', this.collapse, this);  
  
            if(this.view){  
                this.view.setStore(store);  
            }  
        }  
    },  
  
    // private  
    initEvents : function(){  
        Ext.form.ComboBox.superclass.initEvents.call(this);  
  
        this.keyNav = new Ext.KeyNav(this.el, {  
            "up" : function(e){  
                this.inKeyMode = true;  
                this.selectPrev();  
            },  
  
            "down" : function(e){  
                if(!this.isExpanded()){  
                    this.onTriggerClick();  
                }else{  
                    this.inKeyMode = true;  
                    this.selectNext();  
                }  
            },  
  
            "enter" : function(e){  
                this.onViewClick();  
                //return true;  
            },  
  
            "esc" : function(e){  
                this.collapse();  
            },  
  
            "tab" : function(e){  
                this.onViewClick(false);  
                return true;  
            },  
  
            scope : this,  
  
            doRelay : function(foo, bar, hname){  
                if(hname == 'down' || this.scope.isExpanded()){  
                   return Ext.KeyNav.prototype.doRelay.apply(this, arguments);  
                }  
                return true;  
            },  
  
            forceKeyDown : true  
        });  
        this.queryDelay = Math.max(this.queryDelay || 10,  
                this.mode == 'local' ? 10 : 250);  
        this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);  
        if(this.typeAhead){  
            this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);  
        }  
        if(this.editable !== false){  
            this.el.on("keyup", this.onKeyUp, this);  
        }  
        if(this.forceSelection){  
            this.on('blur', this.doForce, this);  
        }  
    },  
  
    onDestroy : function(){  
        if(this.view){  
            this.view.el.removeAllListeners();  
            this.view.el.remove();  
            this.view.purgeListeners();  
        }  
        if(this.list){  
            this.list.destroy();  
        }  
        this.bindStore(null);  
        Ext.form.ComboBox.superclass.onDestroy.call(this);  
    },  
  
    // private  
    fireKey : function(e){  
        if(e.isNavKeyPress() && !this.list.isVisible()){  
            this.fireEvent("specialkey", this, e);  
        }  
    },  
  
    // private  
    onResize: function(w, h){  
        Ext.form.ComboBox.superclass.onResize.apply(this, arguments);  
        if(this.list && this.listWidth === undefined){  
            var lw = Math.max(w, this.minListWidth);  
            this.list.setWidth(lw);  
            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));  
        }  
    },  
  
    // private  
    onDisable: function(){  
        Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);  
        if(this.hiddenField){  
            this.hiddenField.disabled = this.disabled;  
        }  
    },  
    setEditable : function(value){  
        if(value == this.editable){  
            return;  
        }  
        this.editable = value;  
        if(!value){  
            this.el.dom.setAttribute('readOnly', true);  
            this.el.on('mousedown', this.onTriggerClick,  this);  
            this.el.addClass('x-combo-noedit');  
        }else{  
            this.el.dom.setAttribute('readOnly', false);  
            this.el.un('mousedown', this.onTriggerClick,  this);  
            this.el.removeClass('x-combo-noedit');  
        }  
    },  
  
    // private  
    onBeforeLoad : function(){  
        if(!this.hasFocus){  
            return;  
        }  
        this.innerList.update(this.loadingText ?  
               '<div class="loading-indicator">'+this.loadingText+'</div>' : '');  
        this.restrictHeight();  
        this.selectedIndex = -1;  
    },  
  
    // private  
    onLoad : function(){  
        if(!this.hasFocus){  
            return;  
        }  
        if(this.store.getCount() > 0){  
            this.expand();  
            this.restrictHeight();  
            if(this.lastQuery == this.allQuery){  
                if(this.editable){  
                    this.el.dom.select();  
                }  
                if(!this.selectByValue(this.value, true)){  
                    this.select(0, true);  
                }  
            }else{  
                this.selectNext();  
                if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){  
                    this.taTask.delay(this.typeAheadDelay);  
                }  
            }  
        }else{  
            this.onEmptyResults();  
        }  
    },  
  
    // private  
    onTypeAhead : function(){  
        if(this.store.getCount() > 0){  
            var r = this.store.getAt(0);  
            var newValue = r.data[this.displayField];  
            var len = newValue.length;  
            var selStart = this.getRawValue().length;  
            if(selStart != len){  
                this.setRawValue(newValue);  
                this.selectText(selStart, newValue.length);  
            }  
        }  
    },  
    // private  
    onSelect : function(record, index){  
        if(this.fireEvent('beforeselect', this, record, index) !== false){  
            var r = this.store.getAt(index);  
            var newValue = r.data[this.displayField];  
            var check=document.getElementById("checkBox_"+newValue);  
            if(check.className=="checked"){  
                check.className="unchecked"  
            }else{  
                check.className="checked"  
            }  
            var value="";   
            var hiddenValue="";  
            for(var i=0;i<this.store.data.length;i++){  
                 var r = this.store.getAt(i);     
                 newValue = r.data[this.displayField];  
                 check=document.getElementById("checkBox_"+newValue);  
                 if(check.className=="checked"){  
                    value+= r.data[this.displayField]+this.displaySeparator;  
                    hiddenValue+= r.data[this.valueField]+this.valueSeparator;  
                 }  
            }  
            if(value.length>1){  
                value=value.substring(0,value.length-this.displaySeparator.length);  
            }  
            if(hiddenValue.length>1){  
                hiddenValue=hiddenValue.substring(0,value.length-this.valueSeparator.length);  
            }  
            this.setValue(value);  
            this.hiddenField.value=hiddenValue;  
            this.fireEvent('select', this, record, index);  
        }  
    },  
    getValue : function(){  
        if(this.valueField){  
            return typeof this.value != 'undefined' ? this.value : '';  
        }else{  
            return Ext.form.ComboBox.superclass.getValue.call(this);  
        }  
    },  
    
    /**
     * 取消复选框的选中
     */
    unCheckedBox : function(id){
    	 var check=document.getElementById(id);  
    	 //console.log("check="+check);
    	 if(check != null){
    		 check.className="unchecked";
    	 }
    },
  
    /** 
     * Clears any text/value currently set in the field 
     */  
    clearValue : function(){  
        if(this.hiddenField){  
            this.hiddenField.value = '';  
        }  
        this.setRawValue('');  
        this.lastSelectionText = '';  
        this.applyEmptyText();  
    },  
    setValue : function(v){  
        var text = v;  
        if(this.valueField){  
            var r = this.findRecord(this.valueField, v);  
            if(r){  
                text = r.data[this.displayField];  
            }else if(this.valueNotFoundText !== undefined){  
                text = this.valueNotFoundText;  
            }  
        }  
        this.lastSelectionText = text;  
        Ext.form.ComboBox.superclass.setValue.call(this, text);  
        this.value = v;  
    },  
  
    // private  
    findRecord : function(prop, value){  
        var record;  
        if(this.store.getCount() > 0){  
            this.store.each(function(r){  
                if(r.data[prop] == value){  
                    record = r;  
                    return false;  
                }  
            });  
        }  
        return record;  
    },  
  
    // private  
    onViewMove : function(e, t){  
        this.inKeyMode = false;  
    },  
  
    // private  
    onViewOver : function(e, t){  
        if(this.inKeyMode){ // prevent key nav and mouse over conflicts  
            return;  
        }  
        var item = this.view.findItemFromChild(t);  
        if(item){  
            var index = this.view.indexOf(item);  
            this.select(index, false);  
        }  
    },  
  
    // private  
    onViewClick : function(doFocus){  
        var index = this.view.getSelectedIndexes()[0];  
        var r = this.store.getAt(index);  
        if(r){  
            this.onSelect(r, index);  
        }  
        if(doFocus !== false){  
            this.el.focus();  
        }  
    },  
  
    // private  
    restrictHeight : function(){  
        this.innerList.dom.style.height = '';  
        var inner = this.innerList.dom;  
        var fw = this.list.getFrameWidth('tb');  
        var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);  
        this.innerList.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);  
        this.list.beginUpdate();  
        this.list.setHeight(this.innerList.getHeight()+fw+(this.resizable?this.handleHeight:0)+this.assetHeight);  
        this.list.alignTo(this.el, this.listAlign);  
        this.list.endUpdate();  
    },  
  
    // private  
    onEmptyResults : function(){  
        this.collapse();  
    },  
  
    /** 
     * Returns true if the dropdown list is expanded, else false. 
     */  
    isExpanded : function(){  
        return this.list && this.list.isVisible();  
    },  
    selectByValue : function(v, scrollIntoView){  
        if(v !== undefined && v !== null){  
            var r = this.findRecord(this.valueField || this.displayField, v);  
            if(r){  
                this.select(this.store.indexOf(r), scrollIntoView);  
                return true;  
            }  
        }  
        return false;  
    },  
    select : function(index, scrollIntoView){  
          
        this.selectedIndex = index;  
        this.view.select(index);  
        if(scrollIntoView !== false){  
            var el = this.view.getNode(index);  
            if(el){  
                this.innerList.scrollChildIntoView(el, false);  
            }  
        }  
    },  
  
    // private  
    selectNext : function(){  
        var ct = this.store.getCount();  
        if(ct > 0){  
            if(this.selectedIndex == -1){  
                this.select(0);  
            }else if(this.selectedIndex < ct-1){  
                this.select(this.selectedIndex+1);  
            }  
        }  
    },  
  
    // private  
    selectPrev : function(){  
        var ct = this.store.getCount();  
        if(ct > 0){  
            if(this.selectedIndex == -1){  
                this.select(0);  
            }else if(this.selectedIndex != 0){  
                this.select(this.selectedIndex-1);  
            }  
        }  
    },  
  
    // private  
    onKeyUp : function(e){  
        if(this.editable !== false && !e.isSpecialKey()){  
            this.lastKey = e.getKey();  
            this.dqTask.delay(this.queryDelay);  
        }  
    },  
  
    // private  
    validateBlur : function(){  
        return !this.list || !this.list.isVisible();     
    },  
  
    // private  
    initQuery : function(){  
        this.doQuery(this.getRawValue());  
    },  
  
    // private  
    doForce : function(){  
        if(this.el.dom.value.length > 0){  
            this.el.dom.value =  
                this.lastSelectionText === undefined ? '' : this.lastSelectionText;  
            this.applyEmptyText();  
        }  
    },  
    doQuery : function(q, forceAll){  
        if(q === undefined || q === null){  
            q = '';  
        }  
        var qe = {  
            query: q,  
            forceAll: forceAll,  
            combo: this,  
            cancel:false  
        };  
        if(this.fireEvent('beforequery', qe)===false || qe.cancel){  
            return false;  
        }  
        q = qe.query;  
        forceAll = qe.forceAll;  
        if(forceAll === true || (q.length >= this.minChars)){  
            if(this.lastQuery !== q){  
                this.lastQuery = q;  
                if(this.mode == 'local'){  
                    this.selectedIndex = -1;  
                    if(forceAll){  
                        this.store.clearFilter();  
                    }else{  
                        this.store.filter(this.displayField, q);  
                    }  
                    this.onLoad();  
                }else{  
                    this.store.baseParams[this.queryParam] = q;  
                    this.store.load({  
                        params: this.getParams(q)  
                    });  
                    this.expand();  
                }  
            }else{  
                this.selectedIndex = -1;  
                this.onLoad();     
            }  
        }  
    },  
  
    // private  
    getParams : function(q){  
        var p = {};  
        //p[this.queryParam] = q;  
        if(this.pageSize){  
            p.start = 0;  
            p.limit = this.pageSize;  
        }  
        return p;  
    },  
    /** 
     * Hides the dropdown list if it is currently expanded. Fires the 'collapse' event on completion. 
     */  
    collapse : function(){  
        if(!this.isExpanded()){  
            return;  
        }  
        this.list.hide();  
        Ext.getDoc().un('mousewheel', this.collapseIf, this);  
        Ext.getDoc().un('mousedown', this.collapseIf, this);  
        this.fireEvent('collapse', this);  
    },  
    // private  
    collapseIf : function(e){  
        if(!e.within(this.wrap) && !e.within(this.list)){  
            this.collapse();  
        }  
    },  
      
    /** 
     * Expands the dropdown list if it is currently hidden. Fires the 'expand' event on completion. 
     */  
    expand : function(){  
        if(this.isExpanded() || !this.hasFocus){  
            return;  
        }  
        this.list.alignTo(this.wrap, this.listAlign);  
        var hvalueArray=this.hiddenField.value.split(this.valueSeparator);  
        for(var i=0;i<this.store.data.length;i++){  
             var r = this.store.getAt(i);     
             var newValue = r.data[this.displayField];  
              var v=r.data[this.valueField];  
              for(var j=0;j<hvalueArray.length;j++){  
                if(hvalueArray[j]==v){  
                    document.getElementById("checkBox_"+newValue).className="checked";  
                }  
              }  
               
        }   
        this.list.show();  
        Ext.getDoc().on('mousewheel', this.collapseIf, this);  
        Ext.getDoc().on('mousedown', this.collapseIf, this);  
        this.fireEvent('expand', this);  
    },  
  
    // private  
    // Implements the default empty TriggerField.onTriggerClick function  
    onTriggerClick : function(){  
        if(this.disabled){  
            return;  
        }  
        if(this.isExpanded()){  
            this.collapse();  
            this.el.focus();  
        }else {  
            this.onFocus({});  
            if(this.triggerAction == 'all') {  
                this.doQuery(this.allQuery, true);  
            } else {  
                this.doQuery(this.getRawValue());  
            }  
            this.el.focus();  
        }  
    }  
});  
Ext.reg('multicombo', Ext.form.MultiComboBox);  